package com.abso.sunlight.explorer.viewers;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.resource.JFaceColors;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;

import com.abso.sunlight.explorer.LegislatorSearch;
import com.abso.sunlight.explorer.SunlightImages;

/**
 * The node class for the Congress Explorer tree.
 */
public class ExplorerTreeNode {

    /** Shared empty array of nodes. */
    private static final ExplorerTreeNode[] EMPTY_NODE_ARRAY = new ExplorerTreeNode[0];

    /**
     * Type of nodes.
     */
    public enum Type {
        LEGISLATORS, NEW_LEGISLATOR_SEARCH, LEGISLATOR_SEARCH
    };

    /**
     * Creates a tree node wrapping a legislator's search.
     * 
     * @param search   the search to be wrapped.
     * @return   the tree node.
     */
    public static ExplorerTreeNode createSearch(LegislatorSearch search) {
        ExplorerTreeNode node = new ExplorerTreeNode(search, Type.LEGISLATOR_SEARCH, search.getName(),
                SunlightImages.LEGISLATOR_SEARCH.get(), null);
        return node;
    }

    /**
     * Creates a tree node having a specific type.
     * 
     * @param type   the node's type.
     * @return   the tree node.
     */
    public static ExplorerTreeNode create(Type type) {
        switch (type) {
        case LEGISLATORS:
            return new ExplorerTreeNode(type, "Legislators", SunlightImages.LEGISLATORS.get(), null);
        case NEW_LEGISLATOR_SEARCH:
            return new ExplorerTreeNode(type, "New...", SunlightImages.NEW_SEARCH.get(), JFaceColors.getActiveHyperlinkText(null));
        case LEGISLATOR_SEARCH:
            throw new IllegalArgumentException("Use the createSearchNode() method instead");
        }
        throw new IllegalArgumentException("Invalid node type: " + type);
    }

    /** The information wrapped by the node. */
    private Object data;
    
    /** The node's type. */
    private Type type;

    /** The text to be displayed by the node. */
    private String text;

    /** The image to be displayed by the node. */
    private Image image;

    /** The text color. */
    private Color color;

    /** The list of node children. */
    private List<ExplorerTreeNode> children;

    /**
     * Constructs a new node.
     * 
     * @param type   the node's type.
     * @param text   the text to be displayed.
     * @param image   the image to be displayed.
     * @param color   the node's color.
     */
    private ExplorerTreeNode(Type type, String text, Image image, Color color) {
        this(null, type, text, image, color);
    }

    /**
     * Constructs a new node.
     * 
     * @param data   the information to be wrapped in the node.
     * @param type   the node's type.
     * @param text   the text to be displayed.
     * @param image   the image to be displayed.
     * @param color   the node's color.
     */
    private ExplorerTreeNode(Object data, Type type, String text, Image image, Color color) {
        this.data = data;
        this.type = type;
        this.text = text;
        this.image = image;
        this.color = color;
        this.children = new ArrayList<ExplorerTreeNode>();
    }

    /**
     * Returns the information wrapped in the node.
     * 
     * @return   the wrapped information.
     */
    public Object getData() {
        return data;
    }

    /**
     * Returns the node's type.
     * 
     * @return   the node's type.
     */
    public Type getType() {
        return type;
    }

    /**
     * Adds a child node.
     * 
     * @param child   the child node to be added.
     */
    public void addChild(ExplorerTreeNode child) {
        children.add(child);
    }

    /**
     * Removes a child node.
     * 
     * @param child   the child node to be removed.
     */
    public void removeChild(ExplorerTreeNode child) {
        children.remove(child);
    }

    /**
     * Returns the child nodes.
     * 
     * @return   the child nodes.
     */
    public ExplorerTreeNode[] getChildren() {
        return children.toArray(EMPTY_NODE_ARRAY);
    }

    /**
     * Returns the text to be displayed.
     * 
     * @return   the text to be displayed.
     */
    public String getText() {
        return text;
    }

    /**
     * Sets the text to be displayed.
     * 
     * @param text   the text to be displayed.
     */
    public void setText(String text) {
        this.text = text;
    }

    /**
     * Returns the image to be displayed by the node.
     * 
     * @return   the image to be displayed by the node.
     */
    public Image getImage() {
        return image;
    }

    /**
     * Returns the node's color.
     * 
     * @return   the node's color.
     */
    public Color getColor() {
        return color;
    }

    @Override
    public String toString() {
        return getText();
    }

}
